<template>
  <div class="image-upload-container">
    <h2 class="upload-title">图片上传与3D预览</h2>
    
    <!-- 示例模型加载 -->
    <div class="demo-controls">
      <button class="upload-btn" @click="loadMockModel">
        使用示例模型
      </button>
    </div>
    
    <!-- 拖放区域 -->
    <div 
      class="drop-area"
      @dragover.prevent="isDragging = true"
      @dragenter.prevent="isDragging = true"
      @dragleave.prevent="isDragging = false"
      @drop.prevent="handleDrop"
      :class="{ 'drop-active': isDragging }"
    >
      <div class="drop-content">
        <i class="fa fa-cloud-upload upload-icon"></i>
        <p class="drop-text">拖放图片到这里，或</p>
        <label class="browse-btn">
          浏览文件
          <input 
            type="file" 
            accept="image/*" 
            multiple
            @change="handleFileSelect"
            class="file-input"
          >
        </label>
      </div>
    </div>
    
    <!-- 上传限制说明 -->
    <p class="upload-hint">支持 JPG、PNG、GIF 格式，单张图片不超过 5MB</p>
    
    <!-- 预览区域与3D展示 -->
    <div class="preview-container" v-if="previewImages.length > 0 || modelZipUrl">
      <h3 class="preview-title">预览</h3>
      <div class="viewer-layout">
        <div class="upload-column">
          <div class="preview-grid">
        <div 
          class="preview-item" 
          v-for="(image, index) in previewImages" 
          :key="index"
        >
          <img :src="image.url" :alt="'预览图 ' + (index + 1)" class="preview-img">
          <div class="preview-info">
            <span class="file-name">{{ image.name }}</span>
            <span class="file-size">{{ formatFileSize(image.size) }}</span>
          </div>
          <div class="preview-actions">
            <button 
              class="delete-btn" 
              @click="removeImage(index)"
              :disabled="isUploading"
            >
              <i class="fa fa-trash"></i>
            </button>
          </div>
          
          <!-- 上传进度条 -->
          <div class="progress-container" v-if="isUploading && uploadingIndex === index">
            <div 
              class="progress-bar" 
              :style="{ width: uploadProgress + '%' }"
            ></div>
            <span class="progress-text">{{ uploadProgress }}%</span>
          </div>
          
          <!-- 上传状态 -->
          <div class="upload-status" v-if="image.uploaded">
            <span class="success" v-if="image.success">
              <i class="fa fa-check"></i> 上传成功
            </span>
            <span class="error" v-if="!image.success">
              <i class="fa fa-times"></i> 上传失败
              <span v-if="image.errorMsg">: {{ image.errorMsg }}</span>
            </span>
          </div>
        </div>
          </div>
          
          <!-- 上传按钮 -->
          <button 
            class="upload-btn" 
            @click="uploadImages"
            :disabled="isUploading || previewImages.length === 0"
          >
            <i class="fa fa-upload"></i>
            {{ isUploading ? '正在上传...' : '开始上传' }}
          </button>
          
          <!-- 模型生成进度 -->
          <div v-if="isModelPreparing" class="model-progress">
            <div class="model-progress-text">
              模型正在生成与加载中 {{ Math.round(modelProgress) }}%
            </div>
            <div class="model-progress-bar">
              <div class="bar" :style="{ width: modelProgress + '%' }"></div>
            </div>
          </div>
        </div>

        <!-- 3D 视图区域 -->
        <div class="viewer-column" v-if="modelZipUrl">
          <ThreeD 
            :modelZipUrl="modelZipUrl" 
            :previewImageUrl="modelPreviewUrl"
            @progress="onModelProgress"
            @loaded="onModelLoaded"
            @error="onModelError"
          />
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import axios from 'axios';
import ThreeD from './components/3D.vue';

export default {
  components: { ThreeD },
  data() {
    return {
      previewImages: [],
      isDragging: false,
      isUploading: false,
      uploadProgress: 0,
      uploadingIndex: -1,
      // 3D 模型相关
      modelZipUrl: '',
      modelPreviewUrl: '',
      isModelPreparing: false,
      modelProgress: 0,
      mockZipUrl: 'https://hunyuan-prod-1258344699.cos.ap-guangzhou.tencentcos.cn/3d/output/1332891786/5047ade3-78d3-443f-a952-fc15ba12e4b5_0.zip?q-sign-algorithm=sha1&q-ak=AKIDpRovliU1IJ5ctufBSVIq8AwTlnZ5MN8d&q-sign-time=1758616148%3B1758702546&q-key-time=1758616148%3B1758702546&q-header-list=host&q-url-param-list=&q-signature=25a12248e35f77ddac896c46545c28ed1b372b4d',
      mockPreviewUrl: 'https://hunyuan-prod-1258344699.cos.ap-guangzhou.tencentcos.cn/%2F3d/output/1332891786/preview_5047ade3-78d3-443f-a952-fc15ba12e4b5_0.png?q-sign-algorithm=sha1&q-ak=AKIDpRovliU1IJ5ctufBSVIq8AwTlnZ5MN8d&q-sign-time=1758616148%3B1758702546&q-key-time=1758616148%3B1758702546&q-header-list=host&q-url-param-list=&q-signature=729e9bb32a7edd85d4e6af7fd53206bb16783a1a'
    };
  },
  methods: {
    // 处理拖放文件
    handleDrop(e) {
      this.isDragging = false;
      const files = e.dataTransfer.files;
      this.processFiles(files);
    },
    
    // 处理文件选择
    handleFileSelect(e) {
      const files = e.target.files;
      this.processFiles(files);
      // 重置input值，允许重复选择同一文件
      e.target.value = '';
    },
    
    // 处理选择的文件
    processFiles(files) {
      if (!files.length) return;
      
      Array.from(files).forEach(file => {
        // 检查文件类型
        if (!file.type.startsWith('image/')) {
          alert('请选择图片文件！');
          return;
        }
        
        // 检查文件大小 (5MB)
        if (file.size > 5 * 1024 * 1024) {
          alert('图片大小不能超过5MB！');
          return;
        }
        
        // 生成预览URL
        const reader = new FileReader();
        reader.onload = (e) => {
          this.previewImages.push({
            name: file.name,
            size: file.size,
            url: e.target.result,
            file: file,
            uploaded: false,
            success: false,
            errorMsg: ''
          });
        };
        reader.readAsDataURL(file);
      });
    },
    
    // 移除图片
    removeImage(index) {
      this.previewImages.splice(index, 1);
    },
    
    // 格式化文件大小
    formatFileSize(bytes) {
      if (bytes === 0) return '0 Bytes';
      const k = 1024;
      const sizes = ['Bytes', 'KB', 'MB'];
      const i = Math.floor(Math.log(bytes) / Math.log(k));
      return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    },
    
    // 上传图片
    uploadImages() {
      if (this.isUploading) return;
      
      this.uploadImagesSequentially(0);
    },
    
    // 顺序上传图片
    uploadImagesSequentially(index) {
      if (index >= this.previewImages.length) {
        // 所有图片上传完成
        this.isUploading = false;
        this.uploadProgress = 0;
        this.uploadingIndex = -1;
        return;
      }
      
      this.isUploading = true;
      this.uploadingIndex = index;
      this.uploadProgress = 0;
      
      const image = this.previewImages[index];
      const formData = new FormData();
      // 设置参数名为file，符合接口要求
      formData.append('file', image.file);
      
      // 实际接口调用（通过 Vite 代理避免开发环境 CORS）
      axios.post('/api/test/3d', formData, {
        onUploadProgress: (progressEvent) => {
          // 计算上传进度
          if (progressEvent.lengthComputable) {
            this.uploadProgress = Math.round(
              (progressEvent.loaded / progressEvent.total) * 100
            );
          }
        }
      }).then(response => {
        // 上传成功处理
        this.previewImages[index].uploaded = true;
        this.previewImages[index].success = true;
        this.previewImages[index].errorMsg = '';
        
        // 可以在这里处理接口返回的数据
        console.log('上传成功，返回数据:', response.data);
        const resp = response.data || {};
        const data = resp.data || {};
        const files = Array.isArray(data.resultFile3Ds) ? data.resultFile3Ds : [];
        if (files.length > 0) {
          const first = files[0];
          this.modelZipUrl = first.url || '';
          this.modelPreviewUrl = first.previewImageUrl || '';
          // 显示模型准备进度，直到 ThreeD 组件发出 loaded
          this.isModelPreparing = true;
          this.modelProgress = 0;
        }
        
        // 继续上传下一张
        this.uploadImagesSequentially(index + 1);
      }).catch(error => {
        // 上传失败处理
        console.error('上传失败:', error);
        this.previewImages[index].uploaded = true;
        this.previewImages[index].success = false;
        
        // 设置错误信息
        if (error.response && error.response.data && error.response.data.message) {
          this.previewImages[index].errorMsg = error.response.data.message;
        } else {
          this.previewImages[index].errorMsg = '网络错误或服务器无响应';
        }
        
        // 继续上传下一张
        this.uploadImagesSequentially(index + 1);
      });
    },
    onModelProgress(p) {
      this.modelProgress = p;
      this.isModelPreparing = p < 100;
    },
    onModelLoaded() {
      this.modelProgress = 100;
      this.isModelPreparing = false;
    },
    onModelError() {
      this.isModelPreparing = false;
    },
    loadMockModel() {
      this.modelZipUrl = this.mockZipUrl;
      this.modelPreviewUrl = this.mockPreviewUrl;
      this.isModelPreparing = true;
      this.modelProgress = 0;
    }
  },
  watch: {
    // 监听拖放状态
    isDragging(newVal) {
      if (newVal) {
        // 拖入时添加活跃状态
      }
    }
  }
};
</script>

<style scoped>
.image-upload-container {
  max-width: 1100px;
  margin: 2rem auto;
  padding: 0 1rem;
  font-family: 'Arial', sans-serif;
}

.demo-controls { margin-bottom: 1rem; }

.upload-title {
  color: #333;
  text-align: center;
  margin-bottom: 2rem;
  font-size: 1.6rem;
  font-weight: 600;
}

.drop-area {
  border: 2px dashed #ccc;
  border-radius: 12px;
  padding: 3rem 2rem;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s ease;
  background-color: #f9f9f9;
}

.drop-area.drop-active {
  border-color: #42b983;
  background-color: #f0f9f5;
}

.upload-icon {
  font-size: 3rem;
  color: #666;
  margin-bottom: 1rem;
}

.drop-text {
  color: #666;
  margin-bottom: 1.5rem;
  font-size: 1.1rem;
}

.browse-btn {
  display: inline-block;
  background-color: #42b983;
  color: white;
  padding: 0.7rem 1.5rem;
  border-radius: 8px;
  cursor: pointer;
  transition: background-color 0.3s ease, transform 0.2s ease;
  font-weight: 500;
}

.browse-btn:hover {
  background-color: #359e75;
  transform: translateY(-1px);
}

.file-input {
  display: none;
}

.upload-hint {
  text-align: center;
  color: #888;
  font-size: 0.9rem;
  margin: 1rem 0 2rem;
}

.preview-container {
  margin-top: 2rem;
}

.viewer-layout {
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  gap: 1.5rem;
}

.upload-column {}

.viewer-column { min-height: 620px; }

.preview-title {
  color: #333;
  margin-bottom: 1rem;
  border-bottom: 1px solid #eee;
  padding-bottom: 0.5rem;
}

.preview-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 1.5rem;
  margin-bottom: 2rem;
}

.preview-item {
  position: relative;
  border: 1px solid #eee;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 2px 4px rgba(0,0,0,0.05);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
  background: #fff;
}

.preview-item:hover {
  transform: translateY(-3px);
  box-shadow: 0 6px 16px rgba(0,0,0,0.08);
}

.preview-img {
  width: 100%;
  height: 150px;
  object-fit: cover;
  display: block;
}

.preview-info {
  padding: 0.8rem;
  background-color: #f9f9f9;
}

.file-name {
  display: block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 0.9rem;
  margin-bottom: 0.3rem;
}

.file-size {
  font-size: 0.8rem;
  color: #888;
}

.preview-actions {
  position: absolute;
  top: 5px;
  right: 5px;
}

.delete-btn {
  background-color: rgba(255,255,255,0.8);
  border: none;
  border-radius: 50%;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  color: #e74c3c;
  transition: all 0.2s ease;
}

.delete-btn:hover {
  background-color: white;
  transform: scale(1.1);
}

.delete-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.progress-container {
  position: relative;
  height: 5px;
  background-color: #eee;
}

.progress-bar {
  height: 100%;
  background-color: #42b983;
  transition: width 0.3s ease;
}

.progress-text {
  position: absolute;
  right: 5px;
  top: -20px;
  font-size: 0.8rem;
  color: #666;
}

.upload-status {
  padding: 0.5rem;
  text-align: center;
  font-size: 0.9rem;
}

.success {
  color: #2ecc71;
}

.error {
  color: #e74c3c;
}

.upload-btn {
  display: block;
  width: 100%;
  padding: 1rem;
  background-color: #42b983;
  color: white;
  border: none;
  border-radius: 10px;
  font-size: 1rem;
  cursor: pointer;
  transition: background-color 0.3s ease, transform 0.2s ease;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
}

.upload-btn:hover {
  background-color: #359e75;
  transform: translateY(-1px);
}

.upload-btn:disabled {
  background-color: #bdc3c7;
  cursor: not-allowed;
  transform: none;
}

.model-progress { margin-top: 1rem; }
.model-progress-text { color: #666; font-size: 0.9rem; margin-bottom: 0.4rem; }
.model-progress-bar { height: 8px; background: #eee; border-radius: 999px; overflow: hidden; }
.model-progress-bar .bar { height: 100%; background: #42b983; transition: width 0.2s ease; }

/* Responsive */
@media (max-width: 1024px) {
  .viewer-layout {
    grid-template-columns: 1fr;
  }
  .viewer-column { min-height: 520px; }
}

@media (max-width: 640px) {
  .image-upload-container { padding: 0 0.5rem; }
  .preview-grid { grid-template-columns: 1fr 1fr; gap: 1rem; }
  .viewer-column { min-height: 420px; }
}
</style>
